

module Routes

  class ServerIronRouter
    
    def initialize(file_name)
      @rules = {}
      @policies = []
      @server_ip = nil
      @group_ports = {}
      @prefix_routes = []
      @equals_routes = {}
      parse(file_name)
    end
    
    def route_for_uri(uri)
      result_server_info = @equals_routes[uri]
      uri_lowercase = uri.downcase
            
      @prefix_routes.each do |route|
        route.each do |prefix_uri, server_info|
          prefix_uri = '' if prefix_uri.nil?
          prefix_uri = prefix_uri.downcase
          if uri_lowercase.index(prefix_uri) == 0
            result_server_info = server_info
            break
          end
        end
        break if not result_server_info.nil?
      end if result_server_info.nil?
      
      result_server_info
    end
    
    def configuration()
      nil
    end
    
    private      
      def parse(file_name)
        IO.foreach(file_name) do |line| 
          line.rstrip!
          found = csw_rule('prefix', line)
          found = csw_rule('equals', line) if not found
          found = csw_policy_match(line) if not found
          found = server(line) if not found
          found = server_port(line) if not found
        end

        create_rules()
      end    
      
      def csw_rule(type, line)
        result = line.scan(/csw-rule\s+\"(.*)\"\s+url\s+#{type}\s+\"(.*)\"/)
        result.flatten!
        result = array_to_hash(result)

        (@rules[type.to_sym] ||= {}).merge!(result) if not result.empty?

        !result.empty?
      end
      
      def csw_policy?(line)
        (line =~ (/csw-policy.*/)).nil?
      end
      
      def csw_policy_match(line)
        result = line.scan(/\smatch\s+\"(.*)\"\s+forward\s+(.*)/).flatten
        result = line.scan(/\sdefault\s+(.?)forward\s+(.*)/).flatten if result.empty?
        result = array_to_hash(result)
        
        result[:default] = result.delete('') if result.key?('')
        
        # retain order
        @policies << result if not result.empty?
        
        !result.empty?
      end
      
      def server(line)
        result = line.scan(/server\s+real\s+(.+)\s+(.+)/).flatten
        #result = array_to_hash(result)
        
        @server_ip = result[1] if (not result.empty?) and (result.size > 1)
        
        !result.empty?
      end
      
      def server_port(line)
        result = line.scan(/\sport\s+(\d+)\s+group-id\s+(\d+)\s+\d+/).flatten
        result = array_to_hash(result).invert
        
        @group_ports.merge!(result) if not result.empty?

        !result.empty?
      end
      
      def create_rules
        @prefix_routes = []
        
        # create routes
        @policies.each do |item| 
          item.each do |rule, group| 
            rule_key = @rules[:prefix][rule]
            if (not rule_key.nil?) or (rule == :default)
              @prefix_routes  << { rule_key => create_server_info(@server_ip, @group_ports[group]) } 
            else
              rule_key = @rules[:equals][rule]
              @equals_routes.merge!({rule_key => create_server_info(@server_ip, @group_ports[group]) }) if not rule_key.nil?
            end
          end
        end
      end
      
      def create_server_info(host, port)
        { :host => host, :port => port}
      end
      
      def array_to_hash(array)
        hash_result = {}
        if (array.length % 2) == 0
          key = nil
          array.each do | item | 
            if key.nil?
              key = item
            else
              hash_result[key] = item
            end            
          end
        end
        hash_result
      end
  end
  
end
